#include"headFiles.h"
#include "Encoder.h"
using namespace std;

Encoder::Encoder()
{
	Str = NULL;
	StrLength = 0;
}

Encoder::~Encoder()
{
}

void Encoder::WriteBinaryFile(const char* binaryFileName, const char* str, int strLength)
{
	//将main里的字符串写到新建的二进制文件in.bin里
	ofstream outfile;
	outfile.open(binaryFileName);
	if (!outfile)
		throw "Error on Opening file\n";
	outfile.write((char*)&str, strLength);
//	outfile.write(str, strLength);
	outfile.close();
}

void Encoder::ReadBinaryFile(const char* binaryFileName)
{
	//打开二进制文件
	ifstream infile;
	infile.open(binaryFileName);
	if (!infile)
		cout << "Error on Opening file'\n";

	//获取当前文件的大小StrLength
	infile.seekg(0, ios::end);

	StrLength = (int)infile.tellg();
	Str = new char(StrLength);
	infile.seekg(0);

	//读文件，设置Str
	infile.read((char*)&Str, StrLength);
//	infile.read(Str, StrLength);
	infile.close();
}

//判断这张二维码应该使用哪种编码模式：数字、字符、字节
//开始的位置为Str[startI](包括)；结束位为Str[endI](不包括)
Encoder::EnodingModeName Encoder::GetEncodingMode(int startI, int endI)
{
	EnodingModeName m = numeric;	//默认全是数字
	for (int i = startI; i < endI; i++)
	{
		char c = Str[i];
		if (c < '0' || c>'9')//如果出现了一个不是数字的字符，则至少是字符编码
		{
			m = alphanumeric;
			if ((c < 'A' || c>'Z')	//进一步判断，如果出现一个c不在字符编码的范围内，就是字节编码，结束循环
				&& (c != ' ')
				&& (c != '$')
				&& (c != '%')
				&& (c != '*')
				&& (c != '+')
				&& (c != '-')
				&& (c != '.')
				&& (c != '/')
				&& (c != ':'))
			{
				m = byte; break;
			}
		}
	}
	return m;
}

//返回一个字符串，是这一帧的数据区比特流
char* Encoder::GetFrameBits(int startI, int endI)
{
	return GetByteFrameBits(startI, endI);
	//switch (GetEncodingMode(startI, endI))
	//{
	//case numeric:
	//case alphanumeric:
	//case byte:return GetByteFrameBits(startI, endI);
	//default:return GetByteFrameBits(startI, endI);
	//}
}

char* Encoder::GetByteFrameBits(int startI, int endI)
{
    int x = TotalCodeWord * 8
	char* bits = new char[x];


	cout << "这一帧的字符数为" << (endI - startI) << endl;
	//前4位是模式标识符
	cout << "\n前4位是模式标识符，字节编码的标识符为：\n";
	for (int i = 0; i < 4; i++)
	{
		bits[i] = ByteM.ModeIndicator[i] - '0';
		cout << (int)bits[i];
	}

	//假设所用QR版本<10，则字节编码的字符计数符的长度（二进制）为8（用ByteCounterBits表示）
	//从第4位到第12位(不包括)是字符计数符
	//将十进制数len转换为二进制数。(int数据以补码存放，正数的补码就是它的二进制形式，而负数的补码是它相反数的按位取反再加1.这里不涉及负数，所以也可以直接用&1和>>
	int len = endI - startI;
    for (int i = ByteM.BytesCounter + 4 - 1; i >= 4; i--)
	{
		if (len != 0)
		{
			bits[i] = len % 2;
			len = len / 2;
		}
		else
		{
			bits[i] = 0;
		}
	}
	cout << "\n从第4位(包括)到第12位(不包括)是字符计数符：" << endl;
	for (int i = 4; i < ByteM.BytesCounter + 4; i++)
		cout << (int)bits[i];


	//接下来是数据编码，从第12位开始。字节正序，字符的8个比特正序（改成正序了）。编码与ASCII不同
	cout << "\n接下来是数据编码，从第12位开始，往后。字节、比特都正序：\n";
	int headBits = 4 + ByteM.BytesCounter, charNo = 0, i, j = 0;
	char curChar;
	for (i = startI; i < endI; i++)
	{
		charNo = i - startI;	//这一帧的第几个字符
		curChar = Str[i];
		for (j = headBits + (charNo + 1) * 8 - 1; j >= headBits + charNo * 8; j--)	
		{
			bits[j] = curChar & 1;	//取这个char的最低位
			curChar = curChar >> 1;
		}

		//输出，正序。而上面写到bits里的时候是先写8位里的最低位。
		for (int k = headBits + charNo * 8; k < headBits + (charNo+1) * 8; k++)
			cout << (int)bits[k];
		cout << " ";
	}

	//是否达到码字总数？若没有达到则要补0
	int dataBitsLen = 4 + ByteM.BytesCounter + (endI - startI) * 8;
	cout << "\n填完数据后，剩下的" << TotalCodeWord * 8 - dataBitsLen << "个位置用0填充\n\n";
	for (j = dataBitsLen; j < TotalCodeWord * 8; j++)
		bits[j] = 0;	//暂时以0填充

	return bits;
}

char* Encoder::GetAlphaFrameBits(int startI, int endI)
{
	return nullptr;
}

char* Encoder::GetNumFrameBits(int startI, int endI)
{
	return nullptr;
}

void Encoder::CodeFrame(int startI, int endI, int FrameNo)
{
	//获取这一帧的比特流
	char* frameBits = GetFrameBits(startI, endI);

	//链接Drawer类，根据比特流绘图，然后释放内存空间
	Drawer* drawer = new Drawer(522);
	drawer->QRcode(frameBits);
	delete drawer;
	delete[]frameBits;
}

void Encoder::Main(const char* binaryFileName)
{
	ReadBinaryFile(binaryFileName);

	if (StrLength <= ByteM.CapacityPerFrame)
	{
		cout << "只有一帧，最多容纳" << ByteM.CapacityPerFrame << "个字符" << endl;
		CodeFrame(0, StrLength, 0);	
	}
	else
	{
		int totalFrame = StrLength / ByteM.CapacityPerFrame;
		if (StrLength % ByteM.CapacityPerFrame != 0)
			totalFrame++;
		cout << "超过一帧，总帧数为" << totalFrame << endl;

		for (int frameNo = 0; frameNo < totalFrame; frameNo++)
		{
			cout << "\n------------------------------------------------------------------------------";
			cout << "\n第" << frameNo << "帧：";
			CodeFrame(frameNo * ByteM.CapacityPerFrame, (frameNo + 1) * ByteM.CapacityPerFrame, frameNo);
		}
	}
}